package stanaGUI;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import Stana.hierarchicalClustering.AlgoHierarchicalClustering;
import Stana.hierarchicalClustering.PriceQuantityCluster;
import Stana.hierarchicalClustering.PriceQuantityItem;
import stanaGUI.KMeans.AlgoKMeans;
import Stana.kmeansSeqPatternMining.AlgoKMeansSeq;


public class MainWindow extends JFrame {

	private JPanel contentPane;
	private JTextField textFieldParam1;
	private JTextField textFieldParam2;
	private JTextField textFieldParam3;
	private JTextField textFieldParam4;
	private JTextField textFieldParam5;
	private JTextField textFieldParam6;

	private JLabel labelParam1;
	private JLabel labelParam2;
	private JLabel labelParam3;
	private JLabel labelParam4;
	private JLabel labelParam5;
	private JLabel labelParam6;
	private JTextField textFieldInput;
	private JTextField textFieldOutput;

	// IMPORTANT
	private String inputFile =  null;
	private String outputFile =  null;
	private JComboBox<String> comboBox;
	private JTextArea textArea;
	private JButton buttonRun;
	private JCheckBox checkboxOpenOutput;
	private JButton buttonExample;
	static MainWindow mainT;
	static MainWindow frame;
	/**
	 * Launch the application.
	 * @throws UnsupportedLookAndFeelException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
		for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
	        if ("Nimbus".equals(info.getName())) {
	            UIManager.setLookAndFeel(info.getClassName());
	            break;
	        }
	    }
		
		mainT = new MainWindow();
		mainT.WelcomePageGUI();
		new Welcome().setVisible(true);
		//mainT.menuPageGUI();
	}

	public MainWindow () {
	}
	/**
	 * This page is the second screen.
	 */
	void menuPageGUI() {
		//Create and set up the window.
		Toolkit tk = Toolkit.getDefaultToolkit();
		int w = (int)tk.getScreenSize().getWidth();
		int h = (int)tk.getScreenSize().getHeight();
		
		frame =  new MainWindow();
		frame.setLayout(null);
		frame.setTitle("STANA");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(null);
		//frame.setBounds(100, 100, 431, 500);
		frame.setPreferredSize(new Dimension(w, h));
			addWindowListener(new WindowAdapter(){
				public void windowOpened(WindowEvent e){
					frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
				}
			});
		
				
		JPanel panel = (JPanel)frame.getContentPane();
		JPanel entryPanel = new JPanel();
		entryPanel.setBounds(w/2-150, h-130, 300, 50);
		entryPanel.setPreferredSize(new Dimension(300,50));
		ActionListener listener = new MenuItemActionListener(frame);
		
		JMenu file = new JMenu("Data");
		file.setMnemonic('D');
		file.add(menuItem("ProcessFromFile", listener, "From File", 'F', KeyEvent.VK_F));
		file.add(menuItem("ProcessFromDB", listener, "From DB", 'D', KeyEvent.VK_D));
		file.add(menuItem("Exit", listener, "Exit", '0', KeyEvent.VK_W));
		file.addSeparator();
		JMenuBar menubar = new JMenuBar();
		menubar.add(file);
		
		JMenu analysis_menu = new JMenu("Analysis");
		analysis_menu.setMnemonic('A');
		analysis_menu.add(menuItem("ProcessFromFile", listener, "From File", 'F', KeyEvent.VK_F));
		analysis_menu.add(menuItem("ProcessFromDB", listener, "From DB", 'D', KeyEvent.VK_D));
		analysis_menu.add(menuItem("Exit", listener, "Exit", '0', KeyEvent.VK_W));
		menubar.add(analysis_menu);
		frame.setJMenuBar(menubar);
		frame.setVisible(true);
		frame.show();
		// Add a button to enter
		frame.add(entryPanel, BorderLayout.SOUTH);
		//Display the window.
		frame.pack();
		java.awt.EventQueue.invokeLater(new Runnable() { 
		    @Override 
		    public void run() { 
		        frame.toFront(); 
		        frame.repaint(); 
		    } 
		}); 
		
		frame.setVisible(true);
		
	}


	/**
	 * This page is the splash screen.
	 */
	private void WelcomePageGUI() {
	
		//Create and set up the window.
		mainT.setBounds(100, 100, 431, 500);
		mainT.setPreferredSize(new Dimension(420, 200));
		mainT.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainT.setUndecorated(true);
		
		//center the frame
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		mainT.setLocation((dim.width-420)/2,(dim.height-200)/2);
				
		JPanel panel = (JPanel)mainT.getContentPane();
		panel.setPreferredSize(mainT.getPreferredSize());
		JLabel label = new JLabel("");
        label.setBounds(100, 100, panel.getWidth(), panel.getHeight());
        label.setPreferredSize(new Dimension(panel.getWidth(), panel.getHeight()));
        label.setIcon(new ImageIcon(getClass().getResource("/stanaGUI/StanaWelcome.png")));
		label.setBackground(new java.awt.Color(255,255,51));
		label.setForeground(new java.awt.Color(255,255,51));
		label.setOpaque(true);
		
		panel.add(label, BorderLayout.CENTER);
		mainT.pack();
		mainT.setVisible(true);
		
		try { 
	        mainT.toFront(); 
	        mainT.repaint(); 
			Thread.sleep(3000); 
		} catch(InterruptedException ex) { 
			Thread.currentThread().interrupt(); 
		}
		
		mainT.dispose();
	}

	/**
	 * Create the frame.
	 * 
	 */
	public void stanaAlgorithm () {
		// Call the main first screen.

		setResizable(false);
		addWindowListener(new WindowAdapter() {
			public void windowClosed(WindowEvent arg0) {
				System.exit(0);
			}
		});
		setTitle("STANA SelectAlgo");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 474, 561);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		comboBox = new JComboBox<String>(new Vector<String>());
		comboBox.addItem("");
		comboBox.addItem("Hierarchical Clustering");
		comboBox.addItem("Kmeans");
		comboBox.addItem("Sequential Pattern Mining");

		comboBox.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent evt) {
				// COMBOBOX ITEM SELECTION - ITEM STATE CHANGED
				buttonRun.setEnabled(true);
				buttonExample.setEnabled(true);
				if(evt.getStateChange() == ItemEvent.SELECTED) {
					if ("Hierarchical Clustering".equals(evt.getItem())) {
						hideAllParams();
						setParam(textFieldParam1, "Max Quantity :", labelParam1);
						setParam(textFieldParam2, "Max Price :", labelParam2);
					} else if("KMeans".equals(evt.getItem())) {
						hideAllParams();
						buttonRun.setEnabled(true);
					} else if("Sequential Pattern Mining".equals(evt.getItem())) {
						hideAllParams();
						buttonRun.setEnabled(true);
					} else if("".equals(evt.getItem())) {
						hideAllParams();
						buttonRun.setEnabled(false);
					} else {
						buttonExample.setEnabled(false);
					}
				}
			}
		});
		comboBox.setBounds(197, 73, 198, 20);
		contentPane.add(comboBox);

		//  RUN ALGORITHM BUTTON
		buttonRun = new JButton("Run algorithm");
		buttonRun.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try{
					textArea.setText("");
					String choice = (String)comboBox.getSelectedItem();
					if("Hierarchical Clustering".equals(choice)) {
						// Call the corresponding algorithm and execute
						double maxQuantity = getParamAsDouble(textFieldParam1);
						double maxPrice = getParamAsDouble(textFieldParam2);
						System.out.println(" the inputFile " + inputFile);
						System.out.println(" the outputFile " + outputFile);
						System.out.println(" max Quantity " + maxQuantity);
						System.out.println(" max Price " + maxPrice);
						AlgoHierarchicalClustering algo = 
								new AlgoHierarchicalClustering(
										maxQuantity,
										maxPrice,
										inputFile, 
										outputFile);
						algo.runAlgorithm();
						GraphicalRepresentationKmeans graph = new GraphicalRepresentationKmeans();
/*						JPanel panel = graph.PieChart("Stana", "Cluster of Product", algo.getClusters());
						JFrame frameTest = new JFrame("Pie Chart");
						frameTest.setSize(300,300);
						frameTest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
						frameTest.add(panel);
						frameTest.setVisible(true);
						JFrame frameHist = new JFrame("Historical Chart");
						frameHist.setSize(300,300);
						frameHist.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
						JPanel histPanel = graph.Histogram("Histogram Output",algo.getClusters());
						frameHist.add(histPanel);
						frameHist.setVisible(true);*/

					} else if("Sequential Pattern Mining".equals(choice)) {
						// Call the corresponding algorithm and execute
						AlgoKMeansSeq algo = 
								new AlgoKMeansSeq(inputFile, outputFile);
						List<PriceQuantityItem> items = algo.getPriceQuantityItems(); 
						List<PriceQuantityCluster> clusters2 = algo.runAlgorithm(items);
						// Print the results
						algo.writeOutput(clusters2);
						for(PriceQuantityCluster cluster : clusters2){
							System.out.println(cluster.toString());
						}
					} else if("KMeans".equals(choice)) {
						// Call the corresponding algorithm and execute
						AlgoKMeansSeq algo = 
								new AlgoKMeansSeq(inputFile, outputFile);
						List<PriceQuantityCluster> clusters2 = algo.runAlgorithm(
								algo.getPriceQuantityItems());
						// Print the results 
						algo.writeOutput(clusters2);
						for(PriceQuantityCluster cluster : clusters2){
							System.out.println(cluster.toString());
						}
					}
				}catch (NumberFormatException e) {
					JOptionPane.showMessageDialog(null,
							"Error. Please check the parameters of the algorithm.  The format for numbers is incorrect. \n" +
									"\n ERROR MESSAGE = " + e.toString(), "Error",
									JOptionPane.ERROR_MESSAGE);
					return;
				}catch (Exception e) {
					JOptionPane.showMessageDialog(null,
							"An error while trying to run the algorithm. \n ERROR MESSAGE = " + e.toString(), "Error",
							JOptionPane.ERROR_MESSAGE);
					return;
				}

				// IF - the algorithm terminates...
				if(checkboxOpenOutput.isSelected()){
					Desktop desktop = Desktop.getDesktop();
					if (desktop.isSupported(Desktop.Action.OPEN)) {
						try{
							desktop.open(new File(outputFile));
						}catch(IOException e){
							JOptionPane.showMessageDialog(null,
									"The output file failed to open with the default application. " +
											"\n This error occurs if there is no default application on your system " +
											"for opening the output file or the application failed to start. " +
											"\n\n" +
											"To fix the problem, consider changing the extension of the output file to .txt." +
											"\n\n ERROR MESSAGE = " + e.toString(), "Error",
											JOptionPane.ERROR_MESSAGE);
						}catch(SecurityException e){
							JOptionPane.showMessageDialog(null,
									"A security error occured while trying to open the output file. ERROR MESSAGE = " + e.toString(), "Error",
									JOptionPane.ERROR_MESSAGE);
						}catch(Exception e){
							JOptionPane.showMessageDialog(null,
									"An error occured while opening the output file. ERROR MESSAGE = " + e.toString(), "Error",
									JOptionPane.ERROR_MESSAGE);
						}
					}
				}  // END IF - CHECBOX

			}
		});
		buttonRun.setBounds(216, 343, 119, 23);
		contentPane.add(buttonRun);

		JLabel lblChooseAnAlgorithm = new JLabel("Choose an algorithm:");
		lblChooseAnAlgorithm.setBounds(22, 73, 204, 20);
		contentPane.add(lblChooseAnAlgorithm);

		JLabel lblNewLabel = new JLabel("New label");
		lblNewLabel.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				openWebPage("http://www.philippe-fournier-viger.com/spmf/");
			}
		});
		lblNewLabel.setIcon(new ImageIcon(MainWindow.class.getResource("Stana.png")));
		lblNewLabel.setBounds(0, 0, 206, 62);
		contentPane.add(lblNewLabel);

		textFieldParam1 = new JTextField();
		textFieldParam1.setBounds(197, 164, 157, 20);
		contentPane.add(textFieldParam1);
		textFieldParam1.setColumns(10);

		JButton buttonInput = new JButton("...");
		buttonInput.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try{
					File path = null;
					//  CHOOSE INPUT FILE BUTTON
					final JFileChooser fc = new JFileChooser(path);
					fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
					int returnVal = fc.showOpenDialog(MainWindow.this);

					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						textFieldInput.setText(file.getName());
						inputFile = file.getPath();
					}
				}catch(Exception e){
					JOptionPane.showMessageDialog(null,
							"An error occured while opening the input file dialog. ERROR MESSAGE = " + e.toString(), "Error",
							JOptionPane.ERROR_MESSAGE);
				}

			}
		});
		buttonInput.setBounds(364, 104, 32, 23);
		contentPane.add(buttonInput);

		JButton buttonOutput = new JButton("...");
		buttonOutput.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try{
					File path = null;
					final JFileChooser fc;
					if(path != null)
					{
						fc = new JFileChooser(path.getAbsolutePath());
					} else {
						fc = new JFileChooser();
					}
					int returnVal = fc.showSaveDialog(MainWindow.this);

					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						textFieldOutput.setText(file.getName());
						outputFile = file.getPath();
					}

				}catch(Exception e){
					JOptionPane.showMessageDialog(null,
							"An error occured while opening the output file dialog. ERROR MESSAGE = " + e.toString(), "Error",
							JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		buttonOutput.setBounds(364, 133, 32, 23);
		contentPane.add(buttonOutput);

		labelParam1 = new JLabel("Parameter 1:");
		labelParam1.setBounds(22, 167, 156, 14);
		contentPane.add(labelParam1);

		labelParam2 = new JLabel("Parameter 2:");
		labelParam2.setBounds(22, 192, 156, 14);
		contentPane.add(labelParam2);

		labelParam3 = new JLabel("Parameter 3:");
		labelParam3.setBounds(22, 217, 156, 14);
		contentPane.add(labelParam3);

		labelParam4 = new JLabel("Parameter 4:");
		labelParam4.setBounds(22, 239, 156, 14);
		contentPane.add(labelParam4);

		labelParam5 = new JLabel("Parameter 5:");
		labelParam5.setBounds(22, 264, 156, 14);
		contentPane.add(labelParam5);

		labelParam6 = new JLabel("Parameter 6:");
		labelParam6.setBounds(22, 289, 156, 14);
		contentPane.add(labelParam6);

		textFieldParam2 = new JTextField();
		textFieldParam2.setColumns(10);
		textFieldParam2.setBounds(197, 189, 157, 20);
		contentPane.add(textFieldParam2);

		textFieldParam3 = new JTextField();
		textFieldParam3.setColumns(10);
		textFieldParam3.setBounds(197, 214, 157, 20);
		contentPane.add(textFieldParam3);

		textFieldParam4 = new JTextField();
		textFieldParam4.setColumns(10);
		textFieldParam4.setBounds(197, 236, 157, 20);
		contentPane.add(textFieldParam4);

		textFieldParam5 = new JTextField();
		textFieldParam5.setColumns(10);
		textFieldParam5.setBounds(197, 261, 157, 20);
		contentPane.add(textFieldParam5);

		textFieldParam6 = new JTextField();
		textFieldParam6.setColumns(10);
		textFieldParam6.setBounds(197, 286, 157, 20);
		contentPane.add(textFieldParam6);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(10, 377, 437, 145);
		contentPane.add(scrollPane);

		textArea = new JTextArea();
		scrollPane.setViewportView(textArea);
		System.setOut(new PrintStream(new TextAreaOutputStream(textArea)));

		textFieldInput = new JTextField();
		textFieldInput.setText("C:\\Challiz\\tempDB.txt");
		inputFile = "C:\\Challiz\\tempDB.txt";
		textFieldInput.setEditable(false);
		textFieldInput.setBounds(197, 105, 157, 20);
		contentPane.add(textFieldInput);
		textFieldInput.setColumns(10);

		textFieldOutput = new JTextField();
		textFieldOutput.setText("C:\\Challiz\\tempDBOut.txt");
		outputFile = "C:\\Challiz\\tempDBOut.txt";
		textFieldOutput.setEditable(false);
		textFieldOutput.setColumns(10);
		textFieldOutput.setBounds(197, 134, 157, 20);
		contentPane.add(textFieldOutput);

		checkboxOpenOutput = new JCheckBox("Open output file when the algorithm terminates");
		checkboxOpenOutput.setSelected(true);
		checkboxOpenOutput.setBounds(22, 310, 358, 23);
		contentPane.add(checkboxOpenOutput);

		buttonExample = new JButton("?");
		buttonExample.setEnabled(false);
		buttonExample.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				String choice = (String)comboBox.getSelectedItem();
				if ("Hierarchical Clustering".equals(choice)) {
					openWebPage("http://www.philippe-fournier-viger.com/spmf/index.php?link=documentation.php#example10");
				} else if("KMeans".equals(choice)) {
					openWebPage("http://www.philippe-fournier-viger.com/spmf/index.php?link=documentation.php#example8");
				} else if("Sequential Pattern Mining".equals(choice)) {
					openWebPage("http://www.philippe-fournier-viger.com/spmf/index.php?link=documentation.php#example8");
				}
			}
		});
		buttonExample.setBounds(401, 72, 46, 23);
		contentPane.add(buttonExample);

		JLabel lblChooseInputFile = new JLabel("Choose input file");
		lblChooseInputFile.setBounds(22, 108, 97, 14);
		contentPane.add(lblChooseInputFile);

		JLabel lblSetOutputFile = new JLabel("Set output file");
		lblSetOutputFile.setBounds(22, 137, 97, 14);
		contentPane.add(lblSetOutputFile);

		hideAllParams();
	}

	public static void setParam(JTextField textfield, String name, JLabel label){
		label.setText(name);
		textfield.setEnabled(true);
		textfield.setVisible(true);
		label.setVisible(true);
	}

	public double getParamAsDouble(JTextField textfield){
		return Double.parseDouble(textfield.getText());
	}

	public int getParamAsInteger(JTextField textfield){
		return Integer.parseInt(textfield.getText());
	}

	public void hideAllParams(){
		labelParam1.setVisible(false);
		labelParam2.setVisible(false);
		labelParam3.setVisible(false);
		labelParam4.setVisible(false);
		labelParam5.setVisible(false);
		labelParam6.setVisible(false);
		textFieldParam1.setVisible(false);
		textFieldParam2.setVisible(false);
		textFieldParam3.setVisible(false);
		textFieldParam4.setVisible(false);
		textFieldParam5.setVisible(false);
		textFieldParam6.setVisible(false);
	}



	class TextAreaOutputStream extends OutputStream {
		JTextArea textArea;

		public TextAreaOutputStream(JTextArea textArea) {
			this.textArea = textArea;
		}
		public void flush() {
			textArea.repaint();
		}
		public void write(int b) {
			textArea.append(new String(new byte[] {(byte)b}));
		}
	}
	public static JMenuItem menuItem(String label,
			ActionListener listener, String command,
			int mnemonic, int acceleratorKey) {

		JMenuItem item = new JMenuItem(label);
		item.addActionListener(listener);
		item.setActionCommand(command);
		if (mnemonic != 0) item.setMnemonic((char) mnemonic);
		if (acceleratorKey != 0)
			item.setAccelerator(KeyStroke.getKeyStroke(acceleratorKey,java.awt.Event.CTRL_MASK));

		return item;

	}

	public static class MenuItemActionListener implements ActionListener
	{

		Component parent;
		public MenuItemActionListener(Component parent) {
			this.parent = parent;
		}

		public void actionPerformed(ActionEvent e)	{
			String cmd = e.getActionCommand();
			if (cmd.equalsIgnoreCase("From File")) {
				MainWindow frame = new MainWindow();
				frame.setVisible(true);
			} else if (cmd.equalsIgnoreCase("From DB")) {
				// check where we get the mainT
				LoginForm form = new LoginForm(frame);				
			} else if (cmd.equalsIgnoreCase("Please select the Data")) {
				JOptionPane.showMessageDialog(parent, (Object)"Please select the Data from the Data Menu");
			} else {
				System.exit(0);
			}
			// Now do setting of specific variable
		}

	}


	private class SwingAction extends AbstractAction {
		public SwingAction() {
			putValue(NAME, "SwingAction");
			putValue(SHORT_DESCRIPTION, "Some short description");
		}
		public void actionPerformed(ActionEvent e) {
		}
	}

	private void openWebPage(String url) {
		try {
			java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
		}
		catch (java.io.IOException e) {
			System.out.println(e.getMessage());
		}
	}
}
